/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.debug.ui.blocks;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.python.pydev.core.log.Log;
import org.python.pydev.debug.core.Constants;
import org.python.pydev.navigator.PythonLabelProvider;
import org.python.pydev.plugin.PydevPlugin;
import org.python.pydev.plugin.nature.PythonNature;
/**
* A control for selecting a python project.
*/
public class ProjectBlock extends AbstractLaunchConfigurationTab {
private Text fProjectText;
private Button fProjectBrowseButton;
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
Font font = parent.getFont();
Group group = new Group(parent, SWT.NONE);
group.setText("Project");
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
group.setLayoutData(gd);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
group.setLayout(layout);
group.setFont(font);
// Project chooser
fProjectText = new Text(group, SWT.SINGLE | SWT.BORDER);
gd = new GridData(GridData.FILL_HORIZONTAL);
fProjectText.setLayoutData(gd);
fProjectText.setFont(font);
fProjectText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent evt) {
updateLaunchConfigurationDialog();
}
});
fProjectBrowseButton = createPushButton(group, "Browse...", null); //$NON-NLS-1$
fProjectBrowseButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
// Filter out project by python nature
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IProject[] projects = workspace.getRoot().getProjects();
ArrayList<IProject> pythonProjects = new ArrayList<IProject>();
for (IProject project : projects) {
try {
if (project.isOpen() && project.hasNature(PythonNature.PYTHON_NATURE_ID)) {
pythonProjects.add(project);
}
} catch (CoreException exception) {
Log.log(exception);
}
}
projects = pythonProjects.toArray(new IProject[pythonProjects.size()]);
// Only allow the selection of projects, do not present directories
ILabelProvider labelProvider = new PythonLabelProvider();
ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), labelProvider);
dialog.setTitle("Project selection");
dialog.setMessage("Choose a project for the run");
dialog.setElements(projects);
dialog.open();
Object object = dialog.getFirstResult();
if ((object != null) && (object instanceof IProject)) {
IProject project = (IProject) object;
PythonNature pythonNature = PythonNature.getPythonNature(project);
if (pythonNature == null) {
// The project does not have an associated python nature...
String msg = "The selected project must have the python nature associated.";
String title = "Invalid project (no python nature associated).";
ErrorDialog.openError(getShell(), title, msg,
PydevPlugin.makeStatus(IStatus.WARNING, title, null));
}
String projectName = project.getName();
fProjectText.setText(projectName);
}
updateLaunchConfigurationDialog();
}
});
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
*/
public String getName() {
return "Project";
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
*/
public void initializeFrom(ILaunchConfiguration configuration) {
String projectName = "";
try {
projectName = configuration.getAttribute(Constants.ATTR_PROJECT, "");
} catch (CoreException e) {
}
fProjectText.setText(projectName);
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
String value = fProjectText.getText().trim();
setAttribute(configuration, Constants.ATTR_PROJECT, value);
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
// No defaults to set
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
*/
@Override
public boolean isValid(ILaunchConfiguration launchConfig) {
boolean result = super.isValid(launchConfig);
if (result) {
setErrorMessage(null);
setMessage(null);
String projectName = fProjectText.getText();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IResource resource = workspace.getRoot().findMember(projectName);
if (resource == null) {
setErrorMessage("Invalid project");
result = false;
} else if (resource instanceof IProject) {
IProject project = (IProject) resource;
PythonNature nature = PythonNature.getPythonNature(project);
if (nature == null) {
setErrorMessage("Invalid project (no python nature associated).");
result = false;
}
}
}
return result;
}
/**
* Sets attributes in the working copy
*
* @param configuration The configuration to set the attribute in
* @param name Name of the attribute to set
* @param value Value to set
*/
private void setAttribute(ILaunchConfigurationWorkingCopy configuration, String name, String value) {
if (value == null || value.length() == 0) {
configuration.setAttribute(name, (String) null);
} else {
configuration.setAttribute(name, value);
}
}
/**
* Adds a modification listener to the current control.
*
* This is used to update the module browse button, depending
* on the project's python nature.
*
* @param listener The listener to use
*/
public void addModifyListener(ModifyListener listener) {
if (fProjectText == null) {
waitingForProjectTextToExist.add(listener);
} else {
fProjectText.addModifyListener(listener);
for (ModifyListener l : waitingForProjectTextToExist) {
fProjectText.addModifyListener(l);
}
waitingForProjectTextToExist.clear();
}
}
List<ModifyListener> waitingForProjectTextToExist = new ArrayList<ModifyListener>();
}